using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Globalization;
using System.IO;

using Atomic.Libraries;
using Atomic.Structures;
using Atomic.Vasp;

namespace Atomic.Interfaces.Phonopy
{
	[Serializable]
	public class PhonopyDisplacementGenerator //PhonopyPhononDisplacementProblem
	{
		private PhonopyDisplacementGenerator(RawDataFile disp, Structure superStructure, IEnumerable<Structure> displacedStructures)
		{
			Disp = disp;
			SuperStructure = superStructure;
			DisplacedStructures = new ReadOnlyList<Structure>(displacedStructures);
		}
		
		/// <summary>
		/// Generates superstructure with displaced atoms.
		/// </summary>
		public static PhonopyDisplacementGenerator Generate(Structure structure, LatticeRepeatMatrix m)
		{
			// Using Phonopy default displacement:
			// http://phonopy.sourceforge.net/setting-tags.html#displacement-distance
			return Generate(structure, m, 0.01);
		}

		/// <summary>
		/// Generates superstructure with displaced atoms.
		/// </summary>
		public static PhonopyDisplacementGenerator Generate(Structure structure, LatticeRepeatMatrix m, double displacement)
		{
			/*using (TempDirectory temp = new TempDirectory())
			{
				return Generate(structure, m[0, 0], m[0, 1], m[0, 2], m[1, 0], m[1, 1], m[1, 2], m[2, 0], m[2, 1], m[2, 2], displacement, temp.Directory);
			}*/

			return Generate(structure, m[0, 0], m[0, 1], m[0, 2], m[1, 0], m[1, 1], m[1, 2], m[2, 0], m[2, 1], m[2, 2], displacement, new DirectoryInfo("/home/mbjba/ph"));
		}

		/// <summary>
		/// Generates superstructure with displaced atoms.
		/// </summary>
		private static PhonopyDisplacementGenerator Generate(Structure structure, int m11, int m12, int m13, int m21, int m22, int m23, int m31, int m32, int m33, double displacement, DirectoryInfo directory)
		{
			VaspPoscar.Write(structure, directory.AddFile("POSCAR"));

			Process p = new Process();
			p.StartInfo.FileName = "phonopy";
			p.StartInfo.Arguments = string.Format(CultureInfo.InvariantCulture, "-d --dim=\"{0} {1} {2}  {3} {4} {5}  {6} {7} {8}\" --amplitude={9:r}", m11, m12, m13, m21, m22, m23, m31, m32, m33, displacement);
			p.StartInfo.WorkingDirectory = directory.FullName;
			p.StartInfo.UseShellExecute = false;
			p.StartInfo.RedirectStandardOutput = true;
			p.StartInfo.RedirectStandardError = true;

			p.Start();
			p.WaitForExit();

			if (p.ExitCode != 0)
			{
				throw new Exception(string.Format("Running phonopy failed: {0}", p.StandardError.ReadToEnd()));
			}

			List<Structure> displacedStructures = new List<Structure>();
			foreach (FileInfo file in directory.GetFiles())
			{
				if (file.Name.StartsWith("POSCAR-"))
				{
					displacedStructures.Add(VaspPoscar.Read(file));
				}
			}

			return new PhonopyDisplacementGenerator(new RawDataFile(directory.AddFile("disp.yaml")), VaspPoscar.Read(directory.AddFile("SPOSCAR")), displacedStructures);
		}

		public PhonopyResult Collect(IEnumerable<VaspResult> results)
		{
			// the VaspResult corresponding to each of the structure in DisplacedStructures.
			throw new NotImplementedException();
		}

		public RawDataFile Disp
		{
			get;
			private set;
		}

		public Structure SuperStructure
		{
			get;
			private set;
		}

		public ReadOnlyList<Structure> DisplacedStructures
		{
			get;
			private set;
		}
	}
}
